package cn.edu.szu.bigdata.secure;

import cn.edu.szu.bigdata.util.ConfigUtil;
import cn.edu.szu.bigdata.util.FileUtil;
import cn.edu.szu.bigdata.util.IPDataHandler;
import cn.edu.szu.bigdata.util.ValidateConfig;
import com.qihoo.wzws.rzb.cc.CC;
import com.qihoo.wzws.rzb.cc.CCAlgorithm;
import com.qihoo.wzws.rzb.cc.CCDetail;
import com.qihoo.wzws.rzb.exception.SystemConfigException;
import com.qihoo.wzws.rzb.parse.AutomaticLogFormatParser;
import com.qihoo.wzws.rzb.routine.RoutineAnalyze;
import com.qihoo.wzws.rzb.routine.RoutineReportCache;
import com.qihoo.wzws.rzb.secure.po.AttackEntity;
import com.qihoo.wzws.rzb.secure.po.LogEntity;
import com.qihoo.wzws.rzb.util.ConnServerHandler;
import com.qihoo.wzws.rzb.util.DateUtil;
import com.qihoo.wzws.rzb.util.Utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class AnalyzeSingle {
    public static final String clientVersion = "0.6.2";
    public static final boolean product = true;
    private static AnalyzeSingle instance;
    private static String globalHost = "";
    public static String currentFile = "";
    public static String currentTime = "";
    public static boolean useAttack = true;
    public static boolean useCC = false;
    public static boolean useRoutine = false;
    private RoutineAnalyze routine;
    private AttackAnalyzeSingle attack;
    private CCAnalyzeSingle cc;
    private String dir;
    public static String basePath = "";
    public static String jarPath = "";
    public static boolean isJarExecute = false;

    public AnalyzeSingle(RoutineAnalyze routine, AttackAnalyzeSingle attack, CCAnalyzeSingle cc, String dir) {
        this.routine = routine;
        this.attack = attack;
        this.cc = cc;
        this.dir = dir;
    }

    public void execute() {
        String scheduleAnalysis = ConfigUtil.formatConfig.get("schedule_analysis");
        File fileDir = new File(this.dir);
        File[] files;
        if (fileDir.isDirectory()) {
            files = fileDir.listFiles();
            if (files.length >= 1) {
                if ("2".equals(scheduleAnalysis)) {
                    File file = Utils.getlastestFileFromDir(files);
                    RoutineReportCache.logSize += file.length();
                    currentTime = DateUtil.formatDateHour();
                    if (file.getName().indexOf(".") > -1) {
                        currentFile = file.getName().substring(0, file.getName().lastIndexOf("."));
                    } else {
                        currentFile = file.getName();
                    }

                    clearResultHistory();
                    System.out.println("定时任务模式");
                    System.out.println("当前文件下最新文件为：" + file.getName() + ";文件大小为：" + outputFileSize(file.length()));
                    HashMap<String, TreeMap<Long, CCDetail>> allHost = new HashMap();
                    this.rsearch(file, allHost);
                    if (useCC) {
                        this.cc.execute(allHost);
                    }

                    System.gc();
                    allHost.clear();
                    allHost = null;
                } else {
                    currentTime = DateUtil.formatDateHour();
                    if (files[0].getName().indexOf(".") > -1) {
                        currentFile = files[0].getName().substring(0, files[0].getName().lastIndexOf("."));
                    } else {
                        currentFile = files[0].getName();
                    }

                    clearResultHistory();
                    File[] arr = files;
                    int len = files.length;

                    for(int i = 0; i < len; ++i) {
                        File file = arr[i];
                        RoutineReportCache.logSize += file.length();
                        System.out.println("当前文件为：" + file.getName() + ";文件大小为：" + outputFileSize(file.length()));
                        HashMap<String, TreeMap<Long, CCDetail>> allHost = new HashMap();
                        this.rsearch(file, allHost);
                        if (useCC) {
                            this.cc.execute(allHost);
                        }

                        allHost.clear();
                        allHost = null;
                        System.gc();
                    }
                }
            } else {
                System.err.println("输入路径下没有文件，请重新选择！");
                System.out.println("配置无误后请关闭窗口，重新执行。");
            }
        } else if (fileDir.isFile()) {
            RoutineReportCache.logSize = fileDir.length();
            currentTime = DateUtil.formatDateHour();
            if (fileDir.getName().indexOf(".") > -1) {
                currentFile = fileDir.getName().substring(0, fileDir.getName().lastIndexOf("."));
            } else {
                currentFile = fileDir.getName();
            }

            clearResultHistory();
            System.out.println("当前文件为：" + fileDir.getName() + ";文件大小为：" + outputFileSize(fileDir.length()));
            HashMap<String, TreeMap<Long, CCDetail>> allHost = new HashMap();
            this.rsearch(fileDir, allHost);
            if (useCC) {
                this.cc.execute(allHost);
            }

            System.gc();
            allHost.clear();
            files = null;
        } else {
            System.err.println("输入文件路径有误！");
            System.out.println("配置无误后请关闭窗口，重新执行。");
        }

    }

    private static String outputFileSize(long length) {
        String size = "";
        if (length / 1024L / 1024L < 1L) {
            size = length / 1024L + "K";
        } else {
            size = length / 1024L / 1024L + "M";
        }

        return size;
    }

    private static void clearResultHistory() {
        File longf = new File(ReportOutput.getLongUrlFilePath());
        if (longf != null && longf.exists()) {
            longf.delete();
        }

        File attackf = new File(ReportOutput.getAttackFilePath());
        if (attackf != null && attackf.exists()) {
            attackf.delete();
        }

        File ccf = new File(ReportOutput.getCCFilePath());
        if (ccf != null && ccf.exists()) {
            ccf.delete();
        }

        File reportf = new File(ReportOutput.getReportFilePath());
        if (reportf != null && reportf.exists()) {
            reportf.delete();
        }

    }

    public static void main(String[] args) throws SystemConfigException {
        System.out.println("");

        for(int i = 3; i > 0; --i) {
            try {
                Thread.currentThread();
                Thread.sleep(1000L);
            } catch (InterruptedException var35) {
                var35.printStackTrace();
            }
        }

        long start = System.currentTimeMillis();
        String binPath = (new File("")).getAbsolutePath();
//        basePath = binPath.substring(0, binPath.length() - 4);
        basePath = binPath;
        System.out.println("运行前检查...");
        initPath();
        System.out.println("basePath: "+basePath);
        String sys = basePath+ File.separator + "conf" + File.separator + "config.ini";
        String rules = basePath + File.separator + "conf" + File.separator + "rules.ini";
        String ipFilePath = basePath + File.separator + "data" + File.separator + "ipipfree.ipdb";
        String jsPath = basePath + File.separator + "js";
        System.out.println(ipFilePath);
        File sysFile = new File(sys);
        if (sysFile != null && sysFile.exists()) {
            File rulesFile = new File(rules);
            if (rulesFile != null && rulesFile.exists()) {
                File ipFile = new File(ipFilePath);
                if (ipFile != null && ipFile.exists()) {
                    if (!ValidateConfig.validateSysConf(new String[]{sys, rules})) {
                        System.out.println("配置无误后请关闭窗口，重新执行。");
                    } else {
                        IPDataHandler.initIPData(ipFilePath);
                        System.out.println("加载系统配置文件:" + sys);
                        System.out.println("加载分析规则文件:" + rules);
                        String mac = ConfigUtil.formatConfig.get("sign");

//                        try {
//                            ConnServerHandler.requestUpdate(ConfigUtil.formatConfig.get("sign"), "0.6.2", ConfigUtil.formatConfig.get("rule_ver"));
//                        } catch (Exception var34) {
//                        }

                        ValidateConfig.validateRuleConf(rules);
                        long startM = Runtime.getRuntime().freeMemory() / 1024L / 1024L;
                        System.out.println("当前分配的系统内存为：" + startM + "M");
                        System.out.println("检查完毕！");
                        System.out.println("");
                        if ("2".equals(ConfigUtil.formatConfig.get("common_analysis"))) {
                            useRoutine = true;
                        }

                        if ("2".equals(ConfigUtil.formatConfig.get("cc_analysis"))) {
                            CCAnalyzeSingle.initParas();
                            useCC = true;
                        }

                        String tips = "[Web攻击分析";
                        if (useRoutine) {
                            tips = tips + "、日常分析";
                            if (useCC) {
                                tips = tips + "、CC攻击分析";
                            }
                        } else if (useCC) {
                            tips = tips + "、CC攻击分析";
                        }

                        tips = tips + "]";
                        System.out.println("开始分析，请耐心等待(分析1G日志大约需要200秒)...");
                        System.out.println("");
                        File resultDir = new File(ReportOutput.getReportDir());
                        if (!resultDir.exists()) {
                            resultDir.mkdirs();
                        }
                        //复制静态资源到result目录
                        String targetStr=ReportOutput.getReportDir()+File.separator+"js";
                        File jsDir=new File(targetStr);
                        if (!jsDir.exists()){
                            jsDir.mkdirs();
                            FileUtil.copyFolder(jsPath,targetStr);
                        }

                        RoutineAnalyze routine = new RoutineAnalyze();
                        AttackAnalyzeSingle attack = new AttackAnalyzeSingle();
                        CCAnalyzeSingle cc = new CCAnalyzeSingle();
                        instance = new AnalyzeSingle(routine, attack, cc, ConfigUtil.formatConfig.get("log_file"));
                        instance.execute();
                        AttackReportCache.sortAttlist();
                        if (useCC) {
                            AttackReportCache.sortCClist();
                        }

                        ReportOutput.outputFile(AttackReportCache.attackList, AttackReportCache.ccList);
                        long sum = AttackReportCache.attackCount.get() + AttackReportCache.longUrlCount.get();
                        if (useCC) {
                            sum += AttackReportCache.ccCount.get();
                        }


//                        星图上报用户信息
//                        try {
//                            if (AttackReportCache.records.get() > 0L) {
//                                ConnServerHandler.updateUseInfo(mac, "0.6.2", ConfigUtil.formatConfig.get("rule_ver"), AttackReportCache.records.get(), sum);
//                            }
//                        } catch (Exception var33) {
//                        }

                        System.out.println("");
                        long end = System.currentTimeMillis();

//                        星图发送邮件
//                        String email = ConfigUtil.formatConfig.get("xingtu_email");
//                        if (email != null) {
//                            ConnServerHandler.sendMail(mac, "0.6.2", (String)ConfigUtil.formatConfig.get("rule_ver"), email, (String)ConfigUtil.formatConfig.get("log_file"), AttackReportCache.records.get(), sum, (end - start) / 1000L, AttackReportCache.outputOverViewForMail());
//                        }

                        Map<String, String> map = new HashMap();
                        Iterator iter1 = AttackReportCache.attackList.iterator();

                        while(iter1.hasNext()) {
                            AttackEntity entity = (AttackEntity)iter1.next();
                            if (!map.containsKey(entity.getIp() + "|" + entity.getUrl())) {
                                map.put(entity.getIp() + "|" + entity.getUrl(), entity.getRule());
                            }
                        }

                        if (useRoutine) {
                            System.gc();
                            ReportOutput.outputHtml();
                            ReportOutput.outputAttackHtml();
                        }

                        System.out.println("本次进行了" + tips);
                        long count = AttackReportCache.records.get();
                        if (useRoutine) {
                            count = RoutineReportCache.visits;
                        }

                        System.out.println("共分析了" + count + "条访问日志");
                        long costTime = (end - start) / 1000L;
                        if (costTime < 1L) {
                            costTime = 1L;
                        }

                        System.out.println("分析耗时:" + costTime + "秒");
                        System.out.println("其中异常访问" + sum + "条");
                        if (useRoutine) {
                            System.out.println("常规日志分析报告已生成");
                        }

                        System.out.println("");
                        System.out.println("分析结果请打开[星图安装目录result文件夹]查看");
                        System.out.println("本次分析完成！");
                        System.out.println("");
                        int leftsize = map.size();
                        int index = 0;
                        StringBuilder sb = new StringBuilder();
                        Iterator iter2 = map.entrySet().iterator();

//                        while(true) {
//                            while(iter2.hasNext()) {
//                                Map.Entry<String, String> entry = (Map.Entry)iter2.next();
//                                sb.append(entry.getKey() + "|" + entry.getValue());
//                                sb.append(";");
//                                ++index;
//                                --leftsize;
//                                if (index > 500 && leftsize > 0) {
//                                    ConnServerHandler.updateAttackInfo(mac, "0.6.2", ConfigUtil.formatConfig.get("rule_ver"), sb.toString());
//                                    sb = null;
//                                    sb = new StringBuilder();
//                                    index = 0;
//                                } else if (leftsize == 0) {
//                                    ConnServerHandler.updateAttackInfo(mac, "0.6.2", ConfigUtil.formatConfig.get("rule_ver"), sb.toString());
//                                }
//                            }
//
//                            return;
//                        }
                    }
                } else {
                    System.out.println("data/ipipfree.ipdb文件不存在。");
                    System.out.println("确认无误后请关闭窗口，重新执行。");
                }
            } else {
                System.out.println("conf/rule.ini文件不存在。");
                System.out.println("确认无误后请关闭窗口，重新执行。");
            }
        } else {
            System.out.println("conf/config.ini文件不存在。");
            System.out.println("确认无误后请关闭窗口，重新执行。");
        }
    }

    private void rsearch(File file, HashMap<String, TreeMap<Long, CCDetail>> allHost) {
        TreeMap<Long, CCDetail> hostMap = null;
        BufferedReader reader = null;

        try {
            int CharBufferSize = 102400;
            if (file.length() > 209715200L) {
                CharBufferSize = 5242880;
            }

            reader = new BufferedReader(new FileReader(file), CharBufferSize);
            String tempString = null;
//            int day = false;

            while(true) {
                while(true) {
                    String ip;
                    String time;
                    long band;
                    String host;
                    String uri;
                    Date date;
                    while(true) {
                        LogEntity log;
                        do {
                            do {
                                do {
                                    do {
                                        do {
                                            if ((tempString = reader.readLine()) == null) {
                                                return;
                                            }
                                        } while(tempString.startsWith("#"));

                                        log = AutomaticLogFormatParser.parse(tempString);
                                    } while(log == null);
                                } while(log.getRequestUrl() == null);
                            } while(log.getRequestUrl().trim().length() == 0);

                            if (useAttack) {
                                this.attack.execute(log);
                            }

                            if (useRoutine && log.getRequestUrl().length() < 512) {
                                this.routine.execute(log);
                            }
                        } while(!useCC);

                        long s1 = System.currentTimeMillis();
                        ip = log.getIp();
                        time = log.getTime();
                        band = log.getContentLength();
                        host = log.getHost() != null && !log.getHost().trim().isEmpty() ? log.getHost() : globalHost;
                        uri = log.getRequestUrl();
                        if (uri.indexOf("?") > 0) {
                            uri = uri.substring(0, uri.indexOf("?"));
                        }

                        date = null;

                        try {
                            DateFormat commondf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            date = commondf.parse(time);
                            break;
                        } catch (ParseException var33) {
                        }
                    }

                    int day;
                    long minIntervalKey;
                    CCDetail detail;
                    ArrayList ccList;
                    if (allHost.containsKey(host)) {
                        hostMap = (TreeMap)allHost.get(host);

                        try {
                            day = Integer.valueOf(DateUtil.formatDate(date, "yyyyMMdd"));
                        } catch (NumberFormatException var35) {
                            continue;
                        }

                        minIntervalKey = (long)day * 1000L + (long)CCAlgorithm.get5MinInterval(date.getHours(), date.getMinutes());
                        if (hostMap.containsKey(minIntervalKey)) {
                            detail = hostMap.get(minIntervalKey);
                            detail.setCount(detail.getCount() + 1);
                            detail.setBand(detail.getBand() + band);
                            detail.getList().add(new CC(host, uri, ip, time));
                        } else {
                            detail = new CCDetail();
                            detail.setCount(1);
                            detail.setBand(band);
                            ccList = new ArrayList();
                            ccList.add(new CC(host, uri, ip, time));
                            detail.setList(ccList);
                            hostMap.put(minIntervalKey, detail);
                        }
                    } else {
                        hostMap = new TreeMap();

                        try {
                            day = Integer.valueOf(DateUtil.formatDate(date, "yyyyMMdd"));
                        } catch (NumberFormatException var34) {
                            continue;
                        }

                        minIntervalKey = (long)day * 1000L + (long)CCAlgorithm.get5MinInterval(date.getHours(), date.getMinutes());
                        if (hostMap.containsKey(minIntervalKey)) {
                            detail = hostMap.get(minIntervalKey);
                            detail.setCount(detail.getCount() + 1);
                            detail.setBand(detail.getBand() + band);
                            detail.getList().add(new CC(host, uri, ip, time));
                        } else {
                            detail = new CCDetail();
                            detail.setCount(1);
                            detail.setBand(band);
                            ccList = new ArrayList();
                            ccList.add(new CC(host, uri, ip, time));
                            detail.setList(ccList);
                            hostMap.put(minIntervalKey, detail);
                        }

                        allHost.put(host, hostMap);
                    }
                }
            }
        } catch (IOException var36) {
            var36.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException var32) {
                }
            }

        }

    }

    private static void initPath() {
        File jarFile = new File(AnalyzeSingle.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        if (jarFile.getPath().endsWith(".jar")) {
            isJarExecute = true;
            jarPath = jarFile.getPath();
            System.out.println("jarPath"+jarPath);
            basePath = jarFile.getParent();
        } else {
            basePath = jarFile.getParent()+ File.separator + "classes";
        }
    }

    public AttackAnalyzeSingle getAttack() {
        return this.attack;
    }

    public void setAttack(AttackAnalyzeSingle attack) {
        this.attack = attack;
    }
}